package com.fintech.pangu.security.authentication.token.impl;

import com.fintech.pangu.security.authentication.token.AuthenticationRefreshToken;
import com.fintech.pangu.security.authentication.token.AuthenticationToken;
import com.fintech.pangu.security.authentication.token.CompositeAuthenticationToken;
import com.fintech.pangu.security.authentication.token.CompositeAuthenticationTokenServices;
import com.fintech.pangu.security.authentication.token.CompositeAuthenticationTokenStore;
import com.fintech.pangu.security.authentication.token.ExpiringAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.transaction.annotation.Transactional;

/**
 * 默认的复合认证令牌服务
 *
 * @author Trust_FreeDom
 */
public class DefaultCompositeAuthenticationTokenServices implements CompositeAuthenticationTokenServices {

    /**
     * 复合令牌存储
     */
    private CompositeAuthenticationTokenStore compositeTokenStore;


    /**
     * 创建复合的认证令牌
     * @param authentication
     * @return
     */
    @Transactional  // 开启事务支持
    @Override
    public AuthenticationToken createAuthenticationToken(Authentication authentication) {
        // 尝试从存储中获取已有的 AuthenticationToken
        AuthenticationToken existingAuthenticationToken = compositeTokenStore.getAuthenticationToken(authentication);

        AuthenticationRefreshToken refreshToken = null;
        // 如果已有 AuthenticationToken
        if(existingAuthenticationToken != null){
            // 如果认证令牌是可过期的
            if(existingAuthenticationToken instanceof ExpiringAuthenticationToken){
                ExpiringAuthenticationToken existingExpiringAuthenticationToken = (ExpiringAuthenticationToken) existingAuthenticationToken;

                // 已过期
                if(existingExpiringAuthenticationToken.isExpired()){
                    // 如果认证令牌是复合包含刷新令牌的
                    if(existingExpiringAuthenticationToken instanceof CompositeAuthenticationToken){
                        CompositeAuthenticationToken compositeAuthenticationToken = (CompositeAuthenticationToken) existingExpiringAuthenticationToken;

                        if(compositeAuthenticationToken.getRefreshToken() != null){
                            refreshToken = compositeAuthenticationToken.getRefreshToken(); // 暂存刷新令牌

                            // 因为认证令牌被删除，其相关的刷新令牌也先暂时被删除
                            compositeTokenStore.removeAuthenticationRefreshToken(refreshToken);
                        }
                    }

                    // 已过期则删除
                    compositeTokenStore.removeAuthenticationToken(existingExpiringAuthenticationToken);
                }
                // 未过期
                else {
                    // 再次存储，以防更改
                    compositeTokenStore.storeAuthenticationToken(existingExpiringAuthenticationToken, authentication);
                    return existingExpiringAuthenticationToken;
                }
            }
            // 如果令牌存在 且 不具有可过期性
            else{
                compositeTokenStore.storeAuthenticationToken(existingAuthenticationToken, authentication);
                return existingAuthenticationToken;
            }
        }


        // 如果没有refreshToken，创建刷新令牌
        if(refreshToken == null){
            refreshToken = createAuthenticationRefreshToken(authentication);
        }
        // 如果刷新令牌已过期
        else if (System.currentTimeMillis() > refreshToken.getExpiration().getTime()) {
            refreshToken = createAuthenticationRefreshToken(authentication);
        }


        // 创建复合认证令牌
        CompositeAuthenticationToken compositeAuthenticationToken = createCompositeAuthenticationToken(authentication, refreshToken);
        compositeTokenStore.storeAuthenticationToken(compositeAuthenticationToken, authentication);
        // 以防刷新令牌有变动
        refreshToken = compositeAuthenticationToken.getRefreshToken();
        if(refreshToken != null){
            compositeTokenStore.storeAuthenticationRefreshToken(refreshToken, authentication);
        }

        return compositeAuthenticationToken;
    }


    /**
     * 根据 认证信息 和 刷新令牌 创建复合认证令牌
     * @param authentication
     * @param refreshToken
     */
    private CompositeAuthenticationToken createCompositeAuthenticationToken(Authentication authentication, AuthenticationRefreshToken refreshToken) {


        return null;
    }


    /**
     * 获取复合的认证令牌
     * @param authentication
     * @return
     */
    @Override
    public AuthenticationToken getAuthenticationToken(Authentication authentication) {
        return null;
    }


    /**
     * 创建刷新认证令牌
     * @param authentication
     * @return
     */
    @Override
    public AuthenticationRefreshToken createAuthenticationRefreshToken(Authentication authentication) {
        return null;
    }


    /**
     * 刷新认证令牌
     */
    @Override
    public AuthenticationToken refreshAuthenticationToken(String refreshToken) {
        return null;
    }

}
